#include<iostream>
#include<string.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<fcntl.h>
using namespace std;
#define PORT 8111
#define MESSAGE_LEN 1024
#define FD_SIZE 1024 //max client_connect

int main(){
        int socket_fd,accept_fd;
        int ret=-1;
        int on=1;
        char in_buff[MESSAGE_LEN]={0,};
        struct sockaddr_in localaddr;
        struct sockaddr_in remoteaddr;
        int backlog=10;

	
        int flags;
        int max_fd=-1;
        int events=0;
	int curpos=-1;
	fd_set fd_sets;
	int accept_fds[FD_SIZE]={-1,};// vector<int> v(1024,-1);
	for(int i=0;i<1024;i++){
		accept_fds[i]=-1;
	}
	
        socket_fd=socket(AF_INET,SOCK_STREAM,0);// IPV4  TCP  0  create a socket
        if(socket_fd==-1){
                cout<<"failed to create socket!"<<endl;
                exit(-1);
        }

	
	flags=fcntl(socket_fd,F_GETFL,0);
	fcntl(socket_fd,F_SETFL,flags|O_NONBLOCK);//set socket to non-blocking
	max_fd=socket_fd;
	
        ret=setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //set socket option
        if(ret==-1){
                cout<<"failed to set socket option"<<endl;
        }

        localaddr.sin_family=AF_INET;
        localaddr.sin_port=PORT;
        localaddr.sin_addr.s_addr=INADDR_ANY;//INADDR_ANY==0
        bzero(&(localaddr.sin_zero),8);

        ret=bind(socket_fd,(struct sockaddr *)&localaddr,sizeof(struct sockaddr));
        if(ret==-1){
                cout<<"failed to bind addr and port!"<<endl;
                exit(-1);
        }

        ret=listen(socket_fd,backlog);
        if(ret==-1){
                cout<<"failed to listen!"<<endl;
                exit(-1);
        }

        for(;;){
	     FD_ZERO(&fd_sets);//clear fd_sets ==clear all socket
	     FD_SET(socket_fd,&fd_sets);//put listen_socket in fd_sets
	     for(int i=0;i<FD_SIZE;i++){
		if(accept_fds[i]!=-1){//a valid socket
			if(accept_fds[i]>max_fd){
				max_fd=accept_fds[i];
			}
			FD_SET(accept_fds[i],&fd_sets); //if it is a valid client_connect(socket),put it in fd_sets
		}
	     }
		//how many events is driggered and how many file descriptor(fd) is ready
	     events=select(max_fd+1,&fd_sets,NULL,NULL,NULL);
	     if(events<0){
		cout<<"failed to use select!"<<endl;
		break;
	     }
	     else if(events==0){
		cout<<"timeout"<<endl;
		continue;
	     }		
	     else{
		if(FD_ISSET(socket_fd,&fd_sets)){//listen_socket trigger event
			for(int i=0;i<FD_SIZE;i++){
				if(accept_fds[i]==-1){
					curpos=i;
					break;
				}
			}
			//create a new socket accept_fd
             		socklen_t addr_len=sizeof(struct sockaddr);
             		accept_fd=accept(socket_fd,(struct sockaddr *) &remoteaddr,&addr_len);// socket  client_ipAddress
			
			
        		flags=fcntl(accept_fd,F_GETFL,0);
        		fcntl(accept_fd,F_SETFL,flags|O_NONBLOCK);//set socket to non-blocking
			accept_fds[curpos]=accept_fd;//a valid connect
		}
		for(int i=0;i<FD_SIZE;i++){
			if(accept_fds[i]!=-1 && FD_ISSET(accept_fds[i],&fd_sets)){
				memset(in_buff,0,MESSAGE_LEN);
                		ret=recv(accept_fds[i],(void *)in_buff,MESSAGE_LEN,0);
              		  	if(ret==0){
                        		cout<<"client don't send data,disconnected"<<endl;
                        		close(accept_fds[i]);
					break;
                		}
                		cout<<"recveived data is:"<<in_buff<<endl;
                		send(accept_fds[i],(void*)in_buff,MESSAGE_LEN,0);
			}
		}

		
             }
             
        }
        close(socket_fd);
        return 0;
}
